package com.youlai.boot.factory.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.youlai.boot.factory.mapper.ClothingSizesMapper;
import com.youlai.boot.factory.mapper.ColorMapper;
import com.youlai.boot.factory.mapper.CuttingBedDetailsMapper;
import com.youlai.boot.factory.mapper.ProcessMapper;
import com.youlai.boot.factory.mapper.StyleProcessMapper;
import com.youlai.boot.factory.mapper.WorkOrderProcessMapper;
import com.youlai.boot.factory.mapper.WorkReportMapper;
import com.youlai.boot.factory.model.entity.ClothingSizes;
import com.youlai.boot.factory.model.entity.Color;
import com.youlai.boot.factory.model.entity.CuttingBedDetails;
import com.youlai.boot.factory.model.entity.Process;
import com.youlai.boot.factory.model.entity.StyleProcess;
import com.youlai.boot.factory.model.entity.WorkOrderProcess;
import com.youlai.boot.factory.model.entity.WorkReport;
import com.youlai.boot.factory.model.form.CuttingBedDetailsForm;
import com.youlai.boot.factory.model.vo.ProductionProgressVO;
import com.youlai.boot.factory.service.CuttingBedDetailsService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.youlai.boot.factory.mapper.GarmentCuttingBedMapper;
import com.youlai.boot.factory.service.GarmentCuttingBedService;
import com.youlai.boot.factory.model.entity.GarmentCuttingBed;
import com.youlai.boot.factory.model.form.GarmentCuttingBedForm;
import com.youlai.boot.factory.model.query.GarmentCuttingBedQuery;
import com.youlai.boot.factory.model.vo.GarmentCuttingBedVO;
import com.youlai.boot.factory.converter.GarmentCuttingBedConverter;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.ArrayList;
import java.util.HashMap;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import org.springframework.transaction.annotation.Transactional;

import javax.imageio.ImageIO;

/**
 * 裁床单服务实现类
 *
 * @author youlaitech
 * @since 2025-08-24 14:08
 */
@Service
@RequiredArgsConstructor
public class GarmentCuttingBedServiceImpl extends ServiceImpl<GarmentCuttingBedMapper, GarmentCuttingBed> implements GarmentCuttingBedService {

    private final GarmentCuttingBedConverter garmentCuttingBedConverter;
    @Autowired
    private GarmentCuttingBedMapper garmentCuttingBedMapper;

    /**
     * 获取裁床单分页列表
     *
     * @param queryParams 查询参数
     * @return {@link IPage<GarmentCuttingBedVO>} 裁床单分页列表
     */
    @Override
    public IPage<GarmentCuttingBedVO> getGarmentCuttingBedPage(GarmentCuttingBedQuery queryParams) {
        Page<GarmentCuttingBedVO> pageVO = this.baseMapper.getGarmentCuttingBedPage(
                new Page<>(queryParams.getPageNum(), queryParams.getPageSize()),
                queryParams
        );
        pageVO.getRecords().forEach(item -> {
            item.setDetails(cuttingBedDetailsMapper.selectList(new QueryWrapper<CuttingBedDetails>().eq("cutting_bed_id", item.getId())));
        });
        return pageVO;
    }

    @Autowired
    private CuttingBedDetailsService cuttingBedDetailsService;

    /**
     * 获取裁床单表单数据
     *
     * @param id 裁床单ID
     * @return 裁床单表单数据
     */
    @Override
    public GarmentCuttingBedForm getGarmentCuttingBedFormData(Long id) {
        GarmentCuttingBed entity = this.getById(id);
        return garmentCuttingBedConverter.toForm(entity);
    }

    @Autowired
    private ClothingSizesMapper clothingSizesMapper;

    @Autowired
    private ColorMapper colorMapper;


    /**
     * 获取裁床单表单联表数据
     *
     * @param id 裁床单ID
     * @return 裁床单表单数据
     */
    @Override
    public GarmentCuttingBedVO getGarmentCuttingBedJoinFormData(Long id) {
        GarmentCuttingBedVO entity = garmentCuttingBedMapper.getGarmentCuttingBedJoinFormData(id);

        // 获取尺寸名称
        if (StrUtil.isNotBlank(entity.getSize())) {
            List<String> sizeIds = Arrays.asList(entity.getSize().split(","));
            List<ClothingSizes> clothingSizes = clothingSizesMapper.selectList(
                    new QueryWrapper<ClothingSizes>().in("id", sizeIds)
            );
            // 提取尺寸名称并组合成字符串
            String sizeNames = clothingSizes.stream()
                    .map(ClothingSizes::getSizeName)
                    .collect(Collectors.joining(","));
            entity.setSizeNames(sizeNames);
        }

        // 获取颜色名称
        if (StrUtil.isNotBlank(entity.getColor())) {
            List<String> colorIds = Arrays.asList(entity.getColor().split(","));
            List<Color> colors = colorMapper.selectList(
                    new QueryWrapper<Color>().in("color_id", colorIds)
            );
            // 提取颜色名称并组合成字符串
            String colorNames = colors.stream()
                    .map(Color::getColorName)
                    .collect(Collectors.joining(","));
            entity.setColorNames(colorNames);
        }
        return entity;
    }

    @Transactional
    @Override
    public boolean saveGarmentCuttingBed(GarmentCuttingBedForm formData) {
        GarmentCuttingBed entity = garmentCuttingBedConverter.toEntity(formData);

        // 新增裁床的时候 将现有的裁床明细新增 批量新增
        boolean bool = this.save(entity);

        // 此时可以获取到新增的ID
        if (bool) {
            Long newId = entity.getId(); // 获取新增的自增ID
            // 每个明细都设置一下 cutting_bed_id 对应的裁床单id
            List<CuttingBedDetailsForm> details = formData.getDetails().stream()
                    .map(d -> {
                        d.setCuttingBedId(newId);
                        return d;
                    })
                    .collect(Collectors.toList()); // 收集为 List

            // 保存裁床明细等关联操作
            cuttingBedDetailsService.saveBatchCuttingBedDetails(details);
        }

        return bool;
    }


    @Autowired
    private CuttingBedDetailsMapper cuttingBedDetailsMapper;

    @Autowired
    private StyleProcessMapper styleProcessMapper;

    @Autowired
    private ProcessMapper processMapper;

    @Autowired
    private WorkReportMapper workReportMapper;

    @Autowired
    private WorkOrderProcessMapper workOrderProcessMapper;

    /**
     * 更新裁床单
     *
     * @param id       裁床单ID
     * @param formData 裁床单表单对象
     * @return 是否修改成功
     */
    @Override
    @Transactional
    public boolean updateGarmentCuttingBed(Long id, GarmentCuttingBedForm formData) {
        // 设置要更新的ID
        GarmentCuttingBed entity = garmentCuttingBedConverter.toEntity(formData);
        entity.setId(id); // 明确设置ID，确保更新的是指定记录

        // 更新裁床单主表
        boolean result = this.updateById(entity);

        // 如果主表更新成功且有明细数据，则更新明细
        if (result && formData.getDetails() != null && !formData.getDetails().isEmpty()) {
            // 转换 Form 到 Entity
            List<CuttingBedDetails> detailsEntities = formData.getDetails().stream()
                    .map(form -> {
                        CuttingBedDetails detail = new CuttingBedDetails();
                        // 这里需要根据实际的转换逻辑进行转换
                        BeanUtils.copyProperties(form, detail);
                        detail.setId(form.getId());
                        detail.setCuttingBedId(id);
                        // 设置其他属性...
                        return detail;
                    })
                    .collect(Collectors.toList());

            // 使用 MyBatis-Plus 的批量更新方法
            cuttingBedDetailsMapper.updateBatch(detailsEntities);
        }

        return result;
    }


    /**
     * 删除裁床单
     *
     * @param ids 裁床单ID，多个以英文逗号(,)分割
     * @return 是否删除成功
     */
    @Override
    public boolean deleteGarmentCuttingBeds(String ids) {
        Assert.isTrue(StrUtil.isNotBlank(ids), "删除的裁床单数据为空");
        // 逻辑删除
        List<Long> idList = Arrays.stream(ids.split(","))
                .map(Long::parseLong)
                .toList();
        return this.removeByIds(idList);
    }

    /**
     * 生成裁床明细图片
     *
     * @param id 裁床单ID
     * @return Base64编码的图片数据
     */
    @Override
    public String generateImage(Long id) throws IOException {
        GarmentCuttingBedVO garmentCuttingBedVO = garmentCuttingBedMapper.getGarmentCuttingBedJoinFormData(id);

        // 获取裁床明细数据
        List<CuttingBedDetails> cuttingBedDetailsList = cuttingBedDetailsMapper.selectList(
                new QueryWrapper<CuttingBedDetails>().eq("cutting_bed_id", id)
        );

        if (cuttingBedDetailsList == null || cuttingBedDetailsList.isEmpty()) {
            return null;
        }


        // 按颜色分组数据
        Map<String, List<CuttingBedDetails>> colorGroups = cuttingBedDetailsList.stream()
                .collect(Collectors.groupingBy(CuttingBedDetails::getColor));

        // 按照尺码分组
        Map<String, List<CuttingBedDetails>> sizeGroups = cuttingBedDetailsList.stream()
                .collect(Collectors.groupingBy(CuttingBedDetails::getSize));

        // 定义图片参数
        int width = 200 + ((sizeGroups.entrySet().size() + 1) * 100);
        int height = 200 + ((colorGroups.entrySet().size() + 1) * 40); // 根据数据量动态调整高度

        // 创建 BufferedImage
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = image.createGraphics();


        // 设置抗锯齿
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        // 设置背景色
        g2d.setColor(java.awt.Color.WHITE);
        g2d.fillRect(0, 0, width, height);

        // 设置标题字体和颜色
        g2d.setColor(java.awt.Color.BLACK);
        g2d.setFont(new Font("微软雅黑", Font.BOLD, 18));

        // 绘制裁床单标题
        String title = "裁床单";
        FontMetrics fm = g2d.getFontMetrics();
        int titleWidth = fm.stringWidth(title);
        g2d.drawString(title, (width - titleWidth) / 2, 30);

        // 绘制客户信息
        g2d.setFont(new Font("微软雅黑", Font.PLAIN, 14));
        int startY = 60;
        int lineHeight = 25;

        g2d.drawString("客户：" + garmentCuttingBedVO.getCustomerName(), 50, startY);
        g2d.drawString("款号：" + garmentCuttingBedVO.getStyleCode(), 50, startY + lineHeight);
        g2d.drawString("日期：" + garmentCuttingBedVO.getCuttingDate(), 50, startY + 2 * lineHeight);
        g2d.drawString("床次：" + garmentCuttingBedVO.getBedNumber(), 50, startY + 3 * lineHeight);

        // 绘制表格
        int tableStartY = 160;
        int cellHeight = 30;
        int cellWidth = 100;

        // 绘制表头
        g2d.setFont(new Font("微软雅黑", Font.BOLD, 14));
        g2d.setColor(java.awt.Color.BLACK);

        // 颜色列
        g2d.drawRect(50, tableStartY, cellWidth, cellHeight);
        g2d.drawString("颜色", 65, tableStartY + 20);

        // 尺码列
        int index = 0;
        for (String sizeName : sizeGroups.keySet()) {
            int x = 150 + index * cellWidth;
            g2d.drawRect(x, tableStartY, cellWidth, cellHeight);
            g2d.drawString(sizeName, x + 30, tableStartY + 20);
            index++;
        }

        // 合计列 - 根据实际尺码列数量动态计算位置
        int totalColumnX = 150 + sizeGroups.size() * cellWidth;
        g2d.drawRect(totalColumnX, tableStartY, cellWidth, cellHeight);
        g2d.drawString("合计", totalColumnX + 20, tableStartY + 20);

        // 绘制数据行
        g2d.setFont(new Font("微软雅黑", Font.PLAIN, 14));
        g2d.setColor(java.awt.Color.BLACK);


        int rowIndex = 0;
        for (Map.Entry<String, List<CuttingBedDetails>> entry : colorGroups.entrySet()) {
            String colorName = entry.getKey();
            List<CuttingBedDetails> details = entry.getValue();

            // 绘制颜色行
            g2d.drawRect(50, tableStartY + (rowIndex + 1) * cellHeight, cellWidth, cellHeight);
            g2d.drawString(colorName, 65, tableStartY + (rowIndex + 1) * cellHeight + 20);

            // 绘制当前循环的颜色的各尺码数量
            for (int i = 0; i < details.size(); i++) {
                int x = 150 + i * cellWidth;
                g2d.drawRect(x, tableStartY + (rowIndex + 1) * cellHeight, cellWidth, cellHeight);
                g2d.drawString(String.valueOf(details.get(i).getCuttingQuantity()), x + 30, tableStartY + (rowIndex + 1) * cellHeight + 20);
            }

            // 绘制合计列
            g2d.drawRect(totalColumnX, tableStartY + (rowIndex + 1) * cellHeight, cellWidth, cellHeight);
            int total = details.stream().mapToInt(CuttingBedDetails::getCuttingQuantity).sum();
            g2d.drawString(String.valueOf(total), totalColumnX + 20, tableStartY + (rowIndex + 1) * cellHeight + 20);

            rowIndex++;
        }

        // 绘制合计行 - 使用动态计算的位置
        // 绘制合计行 - 使用动态计算的位置
        int totalRowY = tableStartY + (colorGroups.size() + 1) * cellHeight;
        g2d.drawRect(50, totalRowY, cellWidth, cellHeight);
        g2d.drawString("合计", 65, totalRowY + 20);

        // 动态绘制每个尺码的合计数量
        int sizeIndex = 0;
        for (Map.Entry<String, List<CuttingBedDetails>> sizeEntry : sizeGroups.entrySet()) {
            String sizeName = sizeEntry.getKey();
            List<CuttingBedDetails> sizeDetails = sizeEntry.getValue();

            // 计算该尺码在所有颜色中的总数量
            int sizeTotal = sizeDetails.stream()
                    .mapToInt(CuttingBedDetails::getCuttingQuantity)
                    .sum();

            int x = 150 + sizeIndex * cellWidth;
            g2d.drawRect(x, totalRowY, cellWidth, cellHeight);
            g2d.drawString(String.valueOf(sizeTotal), x + 30, totalRowY + 20);
            sizeIndex++;
        }

        // 绘制总计合计
        g2d.drawRect(totalColumnX, totalRowY, cellWidth, cellHeight);
        // 计算所有数据的总合计
        int grandTotal = cuttingBedDetailsList.stream()
                .mapToInt(CuttingBedDetails::getCuttingQuantity)
                .sum();
        g2d.drawString(String.valueOf(grandTotal), totalColumnX + 20, totalRowY + 20);



        // 释放资源
        g2d.dispose();

        // 转换为Base64编码
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ImageIO.write(image, "png", baos);
        byte[] imageBytes = baos.toByteArray();
        return Base64.getEncoder().encodeToString(imageBytes);
    }

    /**
     * 获取裁床单的生产进度
     *
     * @param id 裁床单ID
     * @return 生产进度列表
     */
    @Override
    public List<ProductionProgressVO> getProductionProgress(Long id) {
        // 1. 获取裁床单信息（包括款ID）
        GarmentCuttingBed cuttingBed = this.getById(id);
        if (cuttingBed == null) {
            return new ArrayList<>();
        }

        String styleIdStr = cuttingBed.getStyleId();
        if (StrUtil.isBlank(styleIdStr)) {
            return new ArrayList<>();
        }
        Long styleId = Long.parseLong(styleIdStr);

        // 2. 获取该款的所有工序列表
        List<StyleProcess> styleProcesses = styleProcessMapper.selectList(
                new QueryWrapper<StyleProcess>().eq("style_id", styleId).orderByAsc("process_order")
        );

        if (styleProcesses.isEmpty()) {
            return new ArrayList<>();
        }

        // 3. 获取该裁床单的总数量（从cutting_bed_details表统计）
        List<CuttingBedDetails> details = cuttingBedDetailsMapper.selectList(
                new QueryWrapper<CuttingBedDetails>().eq("cutting_bed_id", id)
        );
        int totalQuantity = details.stream()
                .mapToInt(CuttingBedDetails::getCuttingQuantity)
                .sum();

        // 4. 获取该裁床单关联的所有报工单
        List<WorkReport> workReports = workReportMapper.selectList(
                new QueryWrapper<WorkReport>().eq("cutting_bed_id", id)
        );

        // 5. 获取所有报工单的工序明细
        List<Long> workReportIds = workReports.stream()
                .map(WorkReport::getId)
                .collect(Collectors.toList());

        Map<Long, Integer> processCompletedMap = new HashMap<>();
        if (!workReportIds.isEmpty()) {
            List<WorkOrderProcess> workOrderProcesses = workOrderProcessMapper.selectList(
                    new QueryWrapper<WorkOrderProcess>().in("work_report_id", workReportIds)
            );

            // 按工序ID统计已完成数量
            for (WorkOrderProcess workOrderProcess : workOrderProcesses) {
                Long processId = workOrderProcess.getProcessId();
                Integer quantity = workOrderProcess.getWorkReportQuantity();
                if (quantity != null) {
                    processCompletedMap.put(processId,
                            processCompletedMap.getOrDefault(processId, 0) + quantity);
                }
            }
        }

        // 6. 构建生产进度列表
        List<ProductionProgressVO> progressList = new ArrayList<>();
        for (StyleProcess styleProcess : styleProcesses) {
            ProductionProgressVO progressVO = new ProductionProgressVO();
            progressVO.setProcessId(styleProcess.getId());
            progressVO.setProcessOrder(styleProcess.getProcessOrder());

            // 获取工序名称
            Process process = processMapper.selectById(styleProcess.getProcessId());
            if (process != null) {
                progressVO.setProcessName(process.getProcessName());
            }

            // 设置已完成数量和总数量
            Integer completedQuantity = processCompletedMap.getOrDefault(styleProcess.getId(), 0);
            progressVO.setCompletedQuantity(completedQuantity);
            progressVO.setTotalQuantity(totalQuantity);

            // 设置进度比（已完成/总数量）
            if (totalQuantity > 0) {
                progressVO.setProgressRatio(completedQuantity + "/" + totalQuantity);
            } else {
                progressVO.setProgressRatio("0/0");
                progressVO.setRemark("裁床单暂无明细数据");
            }

            progressList.add(progressVO);
        }

        return progressList;
    }
}
